home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / demostu2 / doom2.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-12-15  |  16.0 KB  |  660 lines

  1. PROGRAM doom2;
  2. {
  3.   DOOM engine, version 0.00002
  4.   - by Bjarke Viksφe
  5.   nov 1994
  6.  
  7.   Second version of the DOOM :) Well, it turned out to be a pretty crude
  8.   one. There's still an annoying bug in the walls which makes them
  9.   flicker... Know what the bug is, just don't care to fix it.
  10.   Only advise to you: play the real thing instead!
  11.   Walls are implemented by extending the ray-casting scheme. Anyway,
  12.   this is just an example showing you that nice wolfy effects can be made
  13.   in less than 700 lines! Completely textured and it can even handle
  14.   ROUND walls !!! Resolution is 160x160 (which is sadly low).
  15.   Ok, perhaps calling it DOOM was aiming a bit high :)
  16. }
  17.  
  18. {$A+,B-,G+,E+,I+,N-,X+}
  19. {$IFDEF DPMI}
  20. {$C FIXED PRELOAD PERMANENT}
  21. {$ENDIF}
  22.  
  23. USES
  24.     DEMOINIT,MOUSE,ILBM256,PICTURE;
  25.  
  26. {{$DEFINE DEBUG}
  27.  
  28. TYPE
  29.     pBunk = ^BunkArray;
  30.     BunkArray = ARRAY[0..254, 0..255] of byte;
  31.     pIntegerArray = ^IntegerArray;
  32.     IntegerArray = ARRAY[0..32765] of integer;
  33.  
  34. CONST
  35.     LINES = 70; {how many lines shall we paint}
  36.     VIEWPOS = 16; {this will ajust the viewer's eyesight}
  37.     STEPBACK = 10; {rotate origo}
  38.     TILT = 31780; {tilt floor how much?}
  39.  
  40.     FILLED_TABLE = $7F00; {offset into map segment where tables are placed}
  41.     WALL_TABLE = 18000*2;
  42.  
  43. VAR
  44.     buffer : pScreen;
  45.     map, tiles : pBunk;
  46.     LineTable : array[1..3] of pIntegerArray;
  47.     xpos,ypos, angle : word;
  48.     CoordPtr : array[0..255] of pointer;
  49.     SinusTable  : array[0..639] of integer;
  50.  
  51. VAR    {DOOM draw private variables}
  52.     tablepos : word;
  53.     height : word;
  54. CONST
  55.     {table that describes how the colours fades away...}
  56.     colourtable : array[1..LINES+1] of byte =
  57.         (224,224,224,224,224,
  58.         192,192,192,192,192,192,
  59.         160,160,160,160,160,160,160,
  60.         128,128,128,128,128,128,128,128,
  61.         96,96,96,96,96,96,96,96,
  62.         64,64,64,64,64,64,64,64,64,
  63.         32,32,32,32,32,32,32,32,32,32,
  64.         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  65.  
  66.  
  67. (*------------------------------------------------*)
  68.  
  69. procedure SetupSinus;
  70. var
  71.     i : integer;
  72.     v, vadd : real;
  73. begin
  74.     v:=0.0;
  75.     vadd:=(2.0*pi/512.0);
  76.     for i:=0 to 639 do begin
  77.         SinusTable[i]:=round(sin(v)*32767);
  78.         v:=v+vadd;
  79.     end;
  80. end;
  81.  
  82. procedure SetColours;
  83. {Setup ugly colours}
  84. var
  85.     i,j,k,fac : integer;
  86. begin
  87.     {calc 8 shades of our 32 colours}
  88.     k:=1;
  89.     fac:=256;
  90.     for i:=1 to 8 do begin
  91.         for j:=1 to (32*3) do begin
  92.             CMAP[k]:=(CMAP[j] * fac) DIV 256;
  93.             inc(k);
  94.         end;
  95.         dec(fac,31);
  96.     end;
  97.     SetCMAP;
  98. end;
  99.  
  100.  
  101. procedure CreateMap;
  102. var
  103.     charmap : array[#0..#128] of byte;
  104. {Create map.
  105.  Characters in strings are indexes to tiles! 'a' is tile #0, 'b' is #1...}
  106.  procedure Strip(ypos : integer; st : string);
  107.  var j : integer;
  108.  begin
  109.         for j:=1 to length(st) do st[j]:=char(charmap[st[j]]);
  110.         Move(st[1],map^[ypos,1],length(st));
  111.  end;
  112. var
  113.     c : char;
  114. begin
  115.     GetMem(map,65535);
  116.     if (Ofs(map^)<>0) then halt;
  117.     FillChar(map^,65535,#0);
  118.  
  119.     charmap[' ']:=0;
  120.     for c:='a' to 'z' do charmap[c]:=ord(c)-ord('a'); {floor textures}
  121.     for c:='1' to '9' do charmap[c]:=ord(c)-ord('1')+24; {wall textures}
  122.     charmap['*']:=128+40; {marks square walls - walltexture taken from floor}
  123.     charmap['@']:=128+41; {marks round pillar}
  124.     charmap['(']:=128+42; {marks round wall}
  125.     charmap[')']:=128+44; {marks round wall}
  126.     charmap['=']:=128+46; {marks left/right square wall}
  127.     charmap[']']:=128+47; {marks up/down square wall}
  128.  
  129.     {floor}
  130.     Strip( 20,'    1111111111111111111111111111111111111                        ');
  131.     Strip( 21,'    1dcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd4   77777                ');
  132.     Strip( 22,'    1cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc4   7ili7                ');
  133.     Strip( 23,'    1dcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdgg4   7kjm7                ');
  134.     Strip( 24,'    1cdc11111111111111111111111111111ggg4   7ini7                ');
  135.     Strip( 25,'    1dcd1              666666555555 4ggg4   7iii7                ');
  136.     Strip( 26,'    1cdc1              6gigigigigi554ggg45555iii5                ');
  137.     Strip( 27,'    1dcd1              666666gigigigigggiiiiliii5                ');
  138.     Strip( 28,'    1cdc1                  655g1gigiggggiiikjmii5                ');
  139.     Strip( 29,'    1dcd1            33333  655gigigigggiiiiniii5                ');
  140.     Strip( 30,'    1cdc1            3fff3  665555554ggg455555555                ');
  141.     Strip( 31,'    1dcd1            3fff3          44444                        ');
  142.     Strip( 32,'    1cdc12222222222222fff2222                                    ');
  143.     Strip( 33,'    1dcoffffffffffffffffffff2                                    ');
  144.     Strip( 34,'    1cofffffffffffffffffffff2                                    ');
  145.     Strip( 35,'    1offfffffffffffffffffff22                                    ');
  146.     Strip( 36,'    122222222222222222222222                                     ');
  147.     {ceiling}
  148.     Strip(148,'    *===================================*                        ');
  149.     Strip(149,'    ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb]   *===*                ');
  150.     Strip(150,'    ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb]   ]eee]                ');
  151.     Strip(151,'    ]bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb]   ]eee]                ');
  152.     Strip(152,'    ]bbb(===========================*bbb]   ]eee]                ');
  153.     Strip(153,'    ]bbb]              *==========* ]bbb]   ]eee]                ');
  154.     Strip(154,'    ]bbb]              ]eeeeeeeeee*=*bbb*===*eee]                ');
  155.     Strip(155,'    ]bbb]              *====)iiiieeeebbbeeeeeeee]                ');
  156.     Strip(156,'    ]bbb]                  **)i@ieeeebbbeeeeeeee]                ');
  157.     Strip(157,'    ]bbb]            *===*  **)iieeeebbbeeeeeeee]                ');
  158.     Strip(158,'    ]bbb]            ]eee]  **======*bbb*=======*                ');
  159.     Strip(159,'    ]bbb]            ]eee]          *===*                        ');
  160.     Strip(160,'    ]bbb*============*eee*==*                                    ');
  161.     Strip(161,'    ]bbpeeeeeeeeeeeeeeeeeeee]                                    ');
  162.     Strip(162,'    ]bpeeeeeeeeeeeeeeeeeeeee]                                    ');
  163.     Strip(163,'    ]peeeeeeeeeeeeeeeeeeeee**                                    ');
  164.     Strip(164,'    *======================*                                     ');
  165. end;
  166.  
  167. procedure CreateTiles;
  168. {Build the tiles. Load .lbm graphics picture}
  169. var
  170.     i,j,k : word;
  171. begin
  172.     GetMem(tiles,65535);
  173.     if (Ofs(tiles^)<>0) then halt;
  174.     FillChar(tiles^,65535,#0);
  175.  
  176.     LoadPix(pScreen(tiles),'doomgfx1.lbm');
  177.     {picture is 320x200. Need to convert it to 256x200}
  178.     j:=0; k:=0;
  179.     for i:=1 to 200 do begin
  180.         Move(pscreen(tiles)^[j],pScreen(tiles)^[k],256);
  181.         inc(j,320);
  182.         inc(k,256);
  183.     end;
  184. end;
  185.  
  186. procedure PrecalcWallRuns;
  187. {Precalc wall-texture heigth data}
  188. var
  189.     a : pIntegerArray;
  190.     i,j,ysize : word;
  191. begin
  192.     a:=pIntegerArray(map);
  193.     i:=WALL_TABLE DIV 2;
  194.     ysize:=161;
  195.     for j:=1 to LINES do begin
  196.         a^[i]:=ysize;
  197.         a^[i+1]:=(64 SHL 8) DIV ysize;
  198.         inc(i,2);
  199.         dec(ysize,2);
  200.     end;
  201. end;
  202.  
  203. procedure PrecalcLines;
  204. {Precalc rotated floor-lines data}
  205. var
  206.     q,p,i, x1,y1,x2,y2 : integer;
  207.     z,sin1,cos1 : integer;
  208.     pos,angle : word;
  209.     cx,cy : longint;
  210.     w : longint;
  211. begin
  212.     for i:=1 to 3 do GetMem(LineTable[i],65535);
  213.  
  214.     p:=1; w:=1 SHL 17;
  215.     pos:=0;
  216.     angle:=0;
  217.     for q:=0 to 255 do begin
  218.         CoordPtr[q]:=@LineTable[p]^[pos];
  219.  
  220.         z:=31100;
  221.         sin1:=SinusTable[angle];
  222.         cos1:=SinusTable[angle+128];
  223.         for i:=1 to LINES do begin
  224.             x1:=LongDiv(-VIEWPOS*65536*4,z); {calc first coord}
  225.             y1:=LongDiv((i+STEPBACK)*longint(TILT)*4,z);
  226.             cx := (LongMul(x1,cos1) - LongMul(y1,sin1)) DIV w; {rotate it}
  227.             cy := (LongMul(x1,sin1) + LongMul(y1,cos1)) DIV w;
  228.             x1:=cx;
  229.             y1:=cy;
  230.             LineTable[p]^[pos]:=x1;
  231.             LineTable[p]^[pos+1]:=y1;
  232.  
  233.             x2:=LongDiv(VIEWPOS*65535*4,z); {calc second coord}
  234.             y2:=LongDiv((i+STEPBACK)*longint(TILT)*4,z);
  235.             cx := (LongMul(x2,cos1) - LongMul(y2,sin1)) DIV w; {rotate it}
  236.             cy := (LongMul(x2,sin1) + LongMul(y2,cos1)) DIV w;
  237.             x2:=cx;
  238.             y2:=cy;
  239.             LineTable[p]^[pos+2]:=(longint(x2-x1) SHL 11) DIV 160;
  240.             LineTable[p]^[pos+3]:=(longint(y2-y1) SHL 11) DIV 160;
  241.             inc(pos,4);
  242.  
  243.             dec(z,330);
  244.         end;
  245.  
  246.         {Check if next set of coords should be placed in other buffer, since
  247.          they cannot all fit into one 64Kb segment!!!}
  248.         if ((pos*2 + (LINES*8)) > 65200) then begin
  249.             inc(p);
  250.             pos:=0;
  251.         end;
  252.         inc(angle,1); {calc next angle}
  253.     end;
  254. end;
  255.  
  256.  
  257.  
  258. procedure InitDemo;
  259. var
  260.     i : integer;
  261. begin
  262.     ClearWholeScreen;
  263.     SetupSinus;
  264.  
  265.     GetMem(buffer,65534);
  266.     FillChar(buffer^,65534,0);
  267.  
  268.     CreateMap;
  269.     CreateTiles;
  270.     SetColours;
  271.     PrecalcWallRuns;
  272.     PrecalcLines;
  273.  
  274.     xpos:=250; ypos:=800;        {starting position}
  275.     angle:=0;                        {start view angle}
  276. end;
  277.  
  278. procedure UninitDemo;
  279. var
  280.     i : integer;
  281. begin
  282.     FreeMem(buffer,65534);
  283.     FreeMem(map,65535);
  284.     FreeMem(tiles,65535);
  285.     for i:=1 to 3 do FreeMem(LineTable[i],65535);
  286. end;
  287.  
  288.  
  289. (*------------------------------------------------*)
  290.  
  291. procedure MoveHero;
  292. var
  293.     x,y, oldx,oldy, sin1,cos1 : integer;
  294.     cx,cy : longint;
  295. begin
  296.     {Determine new rotation angle}
  297.     ReadMouseMotionCounters(x,y);
  298.     angle:=(angle - x) AND 511;
  299.  
  300.     {is hero moving forward?}
  301.     if (LeftButton) then begin
  302.         oldx:=xpos;
  303.         oldy:=ypos;
  304.         sin1:=SinusTable[angle];
  305.         cos1:=SinusTable[angle+128];
  306.         x:=0;  {this is the moving speed}
  307.         y:=(5*(retraces+1)) DIV 2;
  308.         cx := (longmul(x,cos1) - longmul(y,sin1)) DIV 32768;
  309.         cy := (longmul(x,sin1) + longmul(y,cos1)) DIV 32768;
  310.         inc(xpos,cx);
  311.         inc(ypos,cy);
  312.         {has hero bumped into a wall?}
  313.         if (map^[(ypos SHR 5)+128, xpos SHR 5] >= 128) then begin
  314.             xpos:=oldx; ypos:=oldy;
  315.         end;
  316.     end;
  317. end;
  318.  
  319. (*------------------------------------------------*)
  320.  
  321. procedure DrawDoom(x,y, angle : integer; Coords : pointer); assembler;
  322. var
  323.     xadd,yadd,
  324.     mappos,walltablepos : word;
  325.     mapxadd,mapyadd : integer;
  326.     counts : word;
  327.     ceilingtile, flooradd : word;
  328.     colouradd : byte;
  329. asm
  330.     push    ds
  331.  
  332.     {clear "filled-out" lookup-table! Keeps track of blocked vert. lines}
  333.     mov    es,WORD PTR [map+2]
  334.     mov    di,FILLED_TABLE-2
  335.     mov    cx,(160/4)+1
  336.     DB LONG; xor ax,ax
  337.     cld
  338.     DB LONG; rep stosw
  339.  
  340.     {clear middle of screen}
  341.     mov    es,WORD PTR [buffer+2]
  342.     mov    di,70*320
  343.     mov    cx,(25*320)/4
  344.     DB LONG; rep stosw
  345.     mov    di,0    {ES:DI points at screen}
  346.  
  347.     mov    [flooradd],(160*320)
  348.     mov    [colouradd],0
  349.     mov    [walltablepos],WALL_TABLE
  350.  
  351.     mov    ax,WORD PTR [map+2]
  352.     {mov fs,ax} DB $8E,$E0
  353.     mov    ax,WORD PTR [Coords+2]
  354.     {mov gs,ax} DB $8E,$E8
  355.     mov    ax,WORD PTR [Coords]
  356.     mov    [tablepos],ax
  357.  
  358.     mov    [height],LINES
  359.  
  360. {=---- This is the loop for each horizontal line ----=}
  361.  
  362. @y_run:
  363.  
  364.     mov    si,[tablepos]
  365.  
  366.     DB GS; mov    ax,[si+4]                    {setup raycasting run}
  367.     cmp    [angle],256
  368.     jb        @anglelow1
  369.     neg    ax
  370. @anglelow1:
  371.     mov    [xadd],ax
  372.     mov    [mapxadd],1
  373.     or        ax,ax
  374.     jns    @mapxup
  375.     mov    [mapxadd],-1
  376. @mapxup:
  377.     DB GS; mov    ax,[si+6]
  378.     cmp    [angle],256
  379.     jb        @anglelow2
  380.     neg    ax
  381. @anglelow2:
  382.     mov    [yadd],ax
  383.     mov    [mapyadd],256
  384.     or        ax,ax
  385.     jns    @mapyup
  386.     mov    [mapyadd],-256
  387. @mapyup:
  388.  
  389.     DB GS; mov    dx,[si]            {get this line's x/y map starting-pos}
  390.     DB GS; mov    cx,[si+2]
  391.     cmp    [angle],256
  392.     jb        @anglelow3
  393.     neg    cx
  394.     neg    dx
  395. @anglelow3:
  396.     add    dx,[x]                    {add hero's position}
  397.     add    cx,[y]
  398.  
  399.     mov    bx,dx                        {make a copy of our x/y pos}
  400.     mov    ax,cx
  401.  
  402.     shl    dx,11                        {setup x/y raycasting run}
  403.     shl    cx,11
  404.     xor    dx,$8000
  405.     xor    cx,$8000
  406.  
  407.     mov    ds,WORD PTR [tiles+2]
  408.     mov    [counts],160
  409.  
  410.     shr    ax,5                        {Find first tile (size is 32x32)}
  411.     shr    bx,5
  412.     mov    bh,al
  413.     mov    [mappos],bx
  414.     DB FS; mov al,[bx+$8000]    {get ceiling tile-index from map}
  415.     and    al,al                        {is the first one a wall?}
  416.     js        @start_at_wall            {yes, then do wall-run instead...}
  417.     mov    ah,al                        {no, find tile offset in tile-picture}
  418.     and    al,7
  419.     shr    ah,3
  420.     shl    ax,5
  421.     mov    [ceilingtile],ax
  422.     DB FS; mov al,[bx]            {get floor tile-index from map}
  423.     mov    ah,al                        {find tile offset in tile-picture}
  424.     and    al,7
  425.     shr    ah,3
  426.     shl    ax,5
  427.     mov    si,ax
  428.  
  429. {=---- This is the normal floor/ceiling paint run ----=}
  430.  
  431. @x_run1:
  432.  
  433.     mov    bx,[counts]            {is this vertical line blocked?}
  434.     xor    al,al
  435.     DB FS; cmp [bx+FILLED_TABLE],al
  436.     jne    @nodraw1
  437.  
  438.     mov    bh,dh                    {get x-position of pixel}
  439.     mov    bl,ch                    {get y-position of pixel}
  440.     xor    bx,$8080
  441.     shr    bx,3
  442.     and    bx,$1F1F
  443.  
  444.     mov    al,[si+bx]            {get that pixel}
  445.     add    al,[colouradd]
  446.     mov    ah,al
  447.     mov    [es:di],ax            {store ceiling pixel}
  448.     add    bx,[ceilingtile]
  449.     mov    al,[bx]                {get that pixel}
  450.     add    al,[colouradd]
  451.     mov    ah,al
  452.     mov    bx,[flooradd]
  453.     mov    [es:di+bx],ax        {store floor pixels}
  454.  
  455. @nodraw1:
  456.     add    di,2
  457.     add    dx,[xadd]            {add to x-slope}
  458.     jo        @doxadd
  459.     add    cx,[yadd]            {add to y-slope}
  460.     jo        @doyadd
  461. @1:dec    [counts]
  462.     jnz    @x_run1
  463.     jmp    NEAR PTR @nextline
  464.  
  465. {=---- Bumped into a new tile. Calc new address for tile ----=}
  466.  
  467. @doxadd:
  468.     mov    bx,[mappos]
  469.     add    bx,[mapxadd]
  470.     mov    [mappos],bx
  471.  
  472.     add    cx,[yadd]            {add to y-slope also}
  473.     jno    @noyadd
  474. @doyadd:
  475.     mov    bx,[mappos]
  476.     add    bx,[mapyadd]
  477.     mov    [mappos],bx
  478. @noyadd:
  479.  
  480.     DB FS; mov al,[bx+$8000]    {get new ceiling tile-index from map}
  481.  
  482.     push    ax                            {store it so we l8r can check if it's a wall}
  483.     and    al,127
  484.  
  485.     mov    ah,al                        {find tile offset in tile-picture}
  486.     and    al,7
  487.     shr    ah,3
  488.     shl    ax,5
  489.     mov    [ceilingtile],ax
  490.     DB FS; mov al,[bx]            {get new floor tile-index from map}
  491.     mov    ah,al                        {find tile offset in tile-picture}
  492.     and    al,7
  493.     shr    ah,3
  494.     shl    ax,5
  495.     mov    si,ax
  496.  
  497.     pop    ax                            {was it a wall?}
  498.     and    al,al
  499.     js        @2                            {yes, do wall-run}
  500.     jmp    NEAR PTR @1                {no, do floor/ceiling run}
  501.  
  502.  
  503. {=---- We have found a wall. Should handle "round" walls too ----=}
  504.  
  505. @start_at_wall:
  506.     and    al,127
  507.     mov    ah,al                        {find map position in map-buffer}
  508.     and    al,7
  509.     shr    ah,3
  510.     shl    ax,5
  511.     mov    [ceilingtile],ax
  512.     DB FS; mov al,[bx]            {get floor tile-index from map}
  513.     mov    ah,al                        {find map position in map-buffer}
  514.     and    al,7
  515.     shr    ah,3
  516.     shl    ax,5
  517.     mov    si,ax
  518.  
  519. @x_run2:
  520.  
  521.     mov    bx,[counts]            {is this vertical line blocked?}
  522.     xor    al,al
  523.     DB FS; cmp [bx+FILLED_TABLE],al
  524.     jne    @nodraw2
  525.  
  526.     mov    bh,dh                    {get x-position of pixel}
  527.     mov    bl,ch                    {get y-position of pixel}
  528.     xor    bx,$8080
  529.     shr    bx,3
  530.     and    bx,$1F1F
  531.  
  532.     add    bx,[ceilingtile]
  533.     mov    al,[bx]                {check if there is a wall right here}
  534.     and    al,al
  535.     jns    @drawwall            {yes, there is}
  536.     mov    al,29                    {no, paint ceiling and floor with colour #29}
  537.     add    al,[colouradd]
  538.     mov    ah,al
  539.     mov    [es:di],ax            {store ceiling pixels}
  540.     mov    bx,[flooradd]
  541.     mov    [es:di+bx],ax        {store floor pixels}
  542.  
  543. @nodraw2:
  544.     add    di,2
  545.     add    dx,[xadd]            {add to x-slope}
  546.     jo        @doxadd
  547.     add    cx,[yadd]            {add to y-slope}
  548.     jo        @doyadd
  549. @2:dec    [counts]
  550.     jnz    @x_run2
  551.     jmp    NEAR PTR @nextline
  552.  
  553.  
  554. {=----- draw the bloody wall then ----=}
  555.  
  556. @drawwall:
  557.     push    dx
  558.     push    cx
  559.     push    di
  560.     push    si
  561.  
  562.     mov    bx,si
  563.     add    bl,al
  564.  
  565.     mov    si,[walltablepos]
  566.     DB FS; mov cx,[si]        {get wall height}
  567.     DB FS; mov si,[si+2]        {get wall run-add}
  568.     xor    dl,dl
  569.     mov    dh,bh
  570.  
  571. @fillout_wall:
  572.     mov    bh,dh
  573.     mov    al,[bx]                {get that walltexture pixel}
  574.     add    al,[colouradd]
  575.     mov    ah,al
  576.     mov    [es:di],ax            {store wall pixels}
  577.     add    di,320
  578.     add    dx,si
  579.     dec    cx
  580.     jnz    @fillout_wall
  581.  
  582.     pop    si
  583.     pop    di
  584.     pop    cx
  585.     pop    dx
  586.     add    di,2
  587.  
  588.     mov    bx,[counts]            {mark vertical line as blocked}
  589.     mov    al,1
  590.     DB FS; mov [bx+FILLED_TABLE],al
  591.  
  592.     add    dx,[xadd]            {add to x-slope}
  593.     jo        @doxadd
  594.     add    cx,[yadd]            {add to y-slope}
  595.     jo        @doyadd
  596.     dec    [counts]
  597.     jnz    @x_run2
  598.  
  599.  
  600. {=------ OK. We are ready for the next horizontal line ------=}
  601.  
  602. @nextline:
  603.     mov    ax,SEG @DATA
  604.     mov    ds,ax
  605.  
  606.     add    [walltablepos],4
  607.     sub    [flooradd],320*2
  608.     add    [tablepos],8
  609.  
  610.     mov    bx,[height]
  611.     mov    al,[OFFSET colourtable+bx]
  612.     mov    [colouradd],al
  613.  
  614.     dec    [height]
  615.     jnz    @y_run
  616.  
  617.     pop    ds
  618. end;
  619.  
  620. (*------------------------------------------------*)
  621.  
  622. procedure CopyBuffer2Screen; assembler;
  623. asm
  624.     push    ds
  625.     mov    es,SEGA000
  626.     mov    di,20*320
  627.     lds    si,buffer
  628.     mov    cx,(161*320)/2
  629.     cld
  630.     rep movsw
  631.     pop    ds
  632. end;
  633.  
  634.  
  635. (*------------------------------------------------*)
  636.  
  637. procedure RunOnce;
  638. begin
  639.     while retraces=0 do ;
  640.     retraces:=0;
  641. {$IFDEF DEBUG}    VBLANK; SetRGB(0,20,0,0); {$ENDIF}
  642.     CopyBuffer2Screen;
  643.     DrawDoom(xpos,ypos, angle, CoordPtr[angle AND 255]);
  644.     MoveHero;
  645. {$IFDEF DEBUG}    SetRGB(0,0,0,0); {$ENDIF}
  646. end;
  647.  
  648.  
  649. begin
  650.     if NOT MouseDriverPresent then begin writeln('No mouse...'); halt; end;
  651.  
  652.     SetScreenMode(MODE320x200x256);
  653.     InitDemo;
  654.     SetAllInterrupts;
  655.     repeat RunOnce until Key='e';
  656.     RestoreAllInterrupts;
  657.     UninitDemo;
  658.     SetScreenMode(TEXTMODE);
  659. end.
  660.